package mstest.wechat.base.util.bean;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.reflect.MethodSignature;

import java.lang.reflect.Method;
import java.lang.reflect.Parameter;
import java.lang.reflect.Type;

public class MethodUtil {

    private MethodUtil() {
    }

    /**
     * 获得方法的简单签名，作为方法的唯一识别标识
     *
     * @param className 类全名
     * @param method    方法
     * @return 方法唯一识别标识
     */
    public static String getMethodShortSign(String className, Method method) {
        StringBuilder sb = new StringBuilder();
        sb.append(className);
        sb.append('.');
        sb.append(method.getName());
        sb.append('(');
        int i = 0;
        Type[] types = method.getGenericParameterTypes();
        for (Type type : types) {
            sb.append(type.getTypeName());
            if (i < types.length - 1) {
                sb.append(',');
            }
            i++;
        }
        sb.append(')');
        return sb.toString();
    }

    public static String getMethodDescr(ProceedingJoinPoint pjp, long time) {
        MethodSignature methodSignature = (MethodSignature) pjp.getSignature();
        Method method = methodSignature.getMethod();
        String methodIntro = methodSignature.toShortString();
        StringBuilder sb = new StringBuilder();
        sb.append(" [");
        sb.append(methodIntro);
        sb.append("]");
        if (time >= 0) {
            sb.append(" [time:").append(time).append("ms]");
        }
        Parameter[] parameters = method.getParameters();
        Object[] args = pjp.getArgs();
        buildArgs(parameters, args, sb);
        return sb.toString();
    }

    public static void buildArgs(Parameter[] parameters, Object[] args, StringBuilder sb) {
        if (parameters == null || sb == null) {
            return;
        }
        sb.append(" args:[");
        if (args != null) {
            int i = 0;
            for (Object arg : args) {
                sb.append(parameters[i].getName());
                sb.append("=");
                if (arg == null) {
                    sb.append("null");
                } else {
                    sb.append(arg.toString());
                }
                if (i < args.length - 1) {
                    sb.append(", ");
                }
                i++;
            }
        }
        sb.append("]");
    }

    /**
     * 生成setter/getter方法名称，按照头字母大写规则进行生成，如果第二个字母为大写，那么首字母还是小写
     */
    public static String createSetterOrGetterMethodString(String prefix, String fieldName) {
        String first = fieldName.substring(0, 1);
        String second = fieldName.substring(1, 2);
        if (second.equals(second.toUpperCase())) {
            try {
                // 如果第二位为数字，第一位还是需要大写
                Integer.parseInt(second);
                return prefix + first.toUpperCase() + fieldName.substring(1);
            } catch (NumberFormatException e) {
                return prefix + fieldName;
            }
        }
        return prefix + first.toUpperCase() + fieldName.substring(1);
    }

    public static boolean isStringType(Class<?> fieldType) {
        if (fieldType.equals(String.class)) {
            return true;
        }
        return false;
    }

    public static boolean isBoxed(Class<?> fieldType) {
        if (fieldType.equals(Integer.class)) {
            return true;
        }
        if (fieldType.equals(Long.class)) {
            return true;
        }
        if (fieldType.equals(Byte.class)) {
            return true;
        }
        if (fieldType.equals(Short.class)) {
            return true;
        }
        if (fieldType.equals(Boolean.class)) {
            return true;
        }
        if (fieldType.equals(Double.class)) {
            return true;
        }
        if (fieldType.equals(Float.class)) {
            return true;
        }
        return false;
    }

    public static boolean isBoxedBooleanFieldType(Class<?> fieldType) {
        return fieldType.equals(Boolean.class);
    }

    public static String getUnBoxedSubCode(Class<?> fieldType) {
        if (fieldType.equals(Integer.class)) {
            return "intValue()";
        }
        if (fieldType.equals(Long.class)) {
            return "longValue()";
        }
        if (fieldType.equals(Byte.class)) {
            return "byteValue()";
        }
        if (fieldType.equals(Short.class)) {
            return "shortValue()";
        }
        if (fieldType.equals(Boolean.class)) {
            return "booleanValue()";
        }
        if (fieldType.equals(Double.class)) {
            return "doubleValue()";
        }
        if (fieldType.equals(Float.class)) {
            return "floatValue()";
        }
        return null;
    }

    public static boolean isOrigin(Class<?> fieldType) {
        if (fieldType.equals(int.class)) {
            return true;
        }
        if (fieldType.equals(long.class)) {
            return true;
        }
        if (fieldType.equals(byte.class)) {
            return true;
        }
        if (fieldType.equals(short.class)) {
            return true;
        }
        if (fieldType.equals(boolean.class)) {
            return true;
        }
        if (fieldType.equals(double.class)) {
            return true;
        }
        if (fieldType.equals(float.class)) {
            return true;
        }
        return false;
    }

    public static String getBoxedSubCode(Class<?> fieldType) {
        return fieldType.getName() + ".valueOf";
    }

    public static short int2Short(int value) {
        return (short) value;
    }

    public static byte int2Byte(int value) {
        return (byte) value;
    }
}
